﻿using System;
using System.Xml.Linq;

namespace FlightToolkit.SimProp
{
    public enum Type
    {
        None,
        Enum,
        Bool,
        Long,
        Long2,
        Long3,
        Long4,
        ULong,
        Float,
        Float2,
        Float3,
        Float4,
        Matrix,
        Double,
        Byte4,
        Guid,
        String,
        LLA,
        PBH,
        Filetime,
        PropertySet
    }

    internal class TypeDef
    {
        #region Internal
        internal string Name { get; private set; }
        internal Guid Id { get; private set; }
        internal Type Type { get; private set; }

        internal TypeDef(XElement def)
        {
            this.Name = def.Attribute("name").Value;
            var idAttrib = def.Attribute("id");
            if (idAttrib == null)
            {
                idAttrib = def.Attribute("ID");
            }
            this.Id = Guid.Parse(idAttrib.Value);
            if (this.Id != Guid.Empty)
            {
                this.Type = TypeDef.LookupTypeByName(def.Element("binding").Attribute("type").Value);
            }
        }

        internal int GetTypeSize()
        {
            return typeSize[(int)this.Type];
        }
        #endregion

        #region Private
        private static readonly int[] typeSize = 
        {
            0, // None,
            4, // Enum,
            4, // Bool,
            4, // Long,
            8, // Long2,
            12, // Long3,
            16, // Long4,
            4, // ULong,
            4, // Float,
            8, // Float2,
            12, // Float3,
            16, // Float4,
            64, // Matrix,
            8, // Double,
            4, // Byte4,
            16, // Guid,
            -1, // String,
            24, // LLA,
            16, // PBH,
            8, // Filetime,
            -1, // PropertySet
        };

        private static Type LookupTypeByName(string name)
        {
            if (name.Equals("INT", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Enum;
            }
            else if (name.Equals("BOOL", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Bool;
            }
            else if (name.Equals("LONG", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Long;
            }
            else if (name.Equals("LONG2", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Long2;
            }
            else if (name.Equals("LONG3", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Long3;
            }
            else if (name.Equals("LONG4", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Long4;
            }
            else if (name.Equals("ULONG", StringComparison.OrdinalIgnoreCase))
            {
                return Type.ULong;
            }
            else if (name.Equals("FLOAT", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Float;
            }
            else if (name.Equals("FLOAT2", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Float2;
            }
            else if (name.Equals("FLOAT3", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Float3;
            }
            else if (name.Equals("FLOAT4", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Float4;
            }
            else if (name.Equals("MATRIXF32", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Matrix;
            }
            else if (name.Equals("DOUBLE", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Double;
            }
            else if (name.Equals("BYTE4", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Byte4;
            }
            else if (name.Equals("GUID", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Guid;
            }
            else if (name.Equals("LPCWSTR", StringComparison.OrdinalIgnoreCase))
            {
                return Type.String;
            }
            else if (name.Equals("ISimPropertySet*", StringComparison.OrdinalIgnoreCase))
            {
                return Type.PropertySet;
            }
            else if (name.Equals("LATLONALT", StringComparison.OrdinalIgnoreCase))
            {
                return Type.LLA;
            }
            else if (name.Equals("PBH32", StringComparison.OrdinalIgnoreCase))
            {
                return Type.PBH;
            }
            else if (name.Equals("FILETIME", StringComparison.OrdinalIgnoreCase))
            {
                return Type.Filetime;
            }

            return Type.None;
        }
        #endregion
    }
}
